from aiohttp import ClientError, ClientConnectorError
from db import RedisClient
import aiohttp
import asyncio
import time
from asyncio import TimeoutError

#获取网页成功的状态
VAILD_STATUS_CODES = [200]
#检测网站
TEST_URL = 'http://www.tianqihoubao.com/lishi/'
BATCH_TEST_SIZE = 100

class Tester():

    def __init__(self):
        self.redis = RedisClient()

    async def test_single_proxy(self,proxy):
        '''
        测试单个代理的可用性
        :param proxy:代理
        :return:None
        '''
        conn = aiohttp.TCPConnector(ssl=False)
        async with aiohttp.ClientSession(connector=conn) as session:
            try:
                #判断proxy的变量类型是否为bytes，如果是，返回True
                if isinstance(proxy,bytes):
                    proxy = proxy.decode('utf-8')
                real_proxy = 'http://' + proxy
                print('正在测试 ' + proxy)
                async with session.get(TEST_URL,proxy=real_proxy,timeout = 15) as response:
                    if response.status in VAILD_STATUS_CODES:
                        self.redis.max(proxy)
                        print('代理可用 ' + proxy)
                    else:
                        self.redis.decrease(proxy)
                        print('代理不可用 ' + proxy)
            except (ClientError,ClientConnectorError,TimeoutError,AttributeError):
                self.redis.decrease(proxy)
                print('代理请求失败 ' + proxy)

    def run(self):
        '''
        测试住函数
        :return:None
        '''
        print('测试器开始执行')
        try:
            proxies = self.redis.all()
            loop = asyncio.get_event_loop()
            #批量测试
            for i in range(0,len(proxies),BATCH_TEST_SIZE):
                #每次从代理池中最多取出来100个代理进行可用性测试
                test_proxies = proxies[i:i + BATCH_TEST_SIZE]
                tasks = [self.test_single_proxy(proxy) for proxy in test_proxies]
                loop.run_until_complete(asyncio.wait(tasks))
                time.sleep(5)
        except Exception as e:
            print('测试器发生错误： ' , e.args)

# if __name__=='__main__':
#     test = Tester()
#     test.run()